﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Web;
using Ue.Core.FileSystems;
using Ue.Eagle.Runtime.FileSystems;

namespace Ue.Eagle.Runtime
{
    public interface IHostEnvironment
    {
        bool IsFullTrust { get; }

        string MapPath(string virtualPath);

        bool IsAssemblyLoaded(string name);

        void RestartAppDomain();
    }

    public abstract class HostEnvironmentBase : IHostEnvironment
    {
        private readonly IRootFolder rootFolder;

        public HostEnvironmentBase(IRootFolder rootfolder)
        {
            this.rootFolder = rootfolder;
        }

        public IRootFolder RootFolder
        {
            get { return this.rootFolder; }
        }

        public bool IsFullTrust
        {
            get { return AppDomain.CurrentDomain.IsHomogenous && AppDomain.CurrentDomain.IsFullyTrusted; }
        }

        public string MapPath(string virtualPath)
        {
            return this.rootFolder.CombineToPhysicalPath(virtualPath);
        }

        public bool IsAssemblyLoaded(string name)
        {
            return AppDomain.CurrentDomain.GetAssemblies().Any(assembly => new AssemblyName(assembly.FullName).Name == name);
        }

        public abstract void RestartAppDomain();
    }

    public class HostEnvironment : HostEnvironmentBase
    {
        private const string AppConfigPath = "/Web.config";
        private const string HostRestartPath = "/bin/HostRestart";

        public HostEnvironment(IRootFolder rootFolder)
            : base(rootFolder) { }

        public override void RestartAppDomain()
        {
            if (this.IsFullTrust)
            {
                HttpRuntime.UnloadAppDomain();
            }
            else
            {
                bool success = TryWriteBinFolder() || TryWriteConfig();

                if (!success)
                {
                    throw new Exception("应用程序重记失败，请手动重启应用程序。");
                }
            }

            //var httpContext = _httpContextAccessor.Current();
            //if (httpContext != null)
            //{
            //    // Don't redirect posts...
            //    if (httpContext.Request.RequestType == "GET")
            //    {
            //        httpContext.Response.Redirect(HttpContext.Current.Request.ToUrlString(), true /*endResponse*/);
            //    }
            //    else
            //    {
            //        httpContext.Response.ContentType = "text/html";
            //        httpContext.Response.WriteFile(RefreshHtmlPath);
            //        httpContext.Response.End();
            //    }
            //}
        }

        private bool TryWriteConfig()
        {
            try
            {
                File.SetLastWriteTimeUtc(this.MapPath(AppConfigPath), DateTime.UtcNow);
                return true;
            }
            catch
            {
                return false;
            }
        }

        private bool TryWriteBinFolder()
        {
            try
            {
                var binMarker = this.MapPath(HostRestartPath);
                Directory.CreateDirectory(binMarker);

                using (var stream = File.CreateText(Path.Combine(binMarker, "marker.txt")))
                {
                    stream.WriteLine("Restart on '{0}'", DateTime.Now);
                    stream.Flush();
                }
                return true;
            }
            catch
            {
                return false;
            }
        }
    }
}
